Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Resolver] Stale query string values are removed when resolver's component instance ID changes. #74979

Merged
merged 9 commits into from
Aug 13, 2020

Conversation

oatkiller
Copy link
Contributor

@oatkiller oatkiller commented Aug 13, 2020

Summary

The app can show more than 1 Resolver at a time. Each instance has a unique ID called the resolverComponentInstanceID.
When the user interacts with Resolver it will add values to the query string. The query string values will contain the resolverComponentInstanceID. This allows each Resolver to keep its state separate. When resolver unmounts it will remove any query string values related to it.

If Resolver's resolverComponentInstanceID changes it should remove query string values related to the old instance ID. It does not. This PR fixes that.

Note: I don't know if it was possible for this bug to actually happen. I can't make it happen, but depending on how Resolver is mounted by its consumers it could

Checklist

For maintainers

@oatkiller oatkiller added release_note:fix Team:Endpoint Data Visibility Team managing the endpoint resolver Feature:Resolver Security Solution Resolver feature v7.10.0 labels Aug 13, 2020
@oatkiller oatkiller requested review from a team as code owners August 13, 2020 17:57
@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility)

@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-app-team (Feature:Resolver)

return {
selectedNode: urlSearchParams.getAll(`resolver-${this.resolverComponentInstanceID}-id`),
};
public get historyLocationSearch(): string {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is weird. Any suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with it, attempting to rename things that are built in and already have names usually just leads to more confusion imo

/**
* Change the component instance ID (updates the React component props.)
*/
public set resolverComponentInstanceID(value: string) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts? @michaelolo24

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 , but would it be useful to be able to update the databaseDocumentId and componentInstanceId? We don't currently do it, but there could be a situation where we load another tree within an existing resolver window when a user requests additional data. That might just be a page change, but yea. Either way, this can be refactored to that later on as well if necessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@@ -98,7 +99,9 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children',
}))
).toYieldEqualTo({
// Just the second child should be marked as selected in the query string
queryStringSelectedNode: [entityIDs.secondChild],
search: urlSearch(resolverComponentInstanceID, {
selectedEntityID: entityIDs.secondChild,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now compares the url query strings.

selectedNode: [entityIDs.origin],
});
await expect(simulator().map(() => simulator().historyLocationSearch)).toYieldEqualTo(
urlSearch(resolverComponentInstanceID, {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now compares the url query strings.


// the resolver component instance ID, used by the react code to distinguish piece of global state from those used by other resolver instances
const resolverComponentInstanceID = 'oldID';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could use a doc level comment. Something like what is in the description of this PR.

import { useSelector } from 'react-redux';
import { useEffectOnce } from 'react-use';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kqualters-elastic i blame you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is on your permanent record

[uniqueCrumbEventKey]: newCrumbs.crumbEvent,
};
(queryStringState: CrumbInfo) => {
const urlSearchParams = new URLSearchParams(urlSearch);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using URLSearchParams instead of external dep

crumbEvent: valueForParam(crumbEvent),
crumbId: valueForParam(crumbId),
// Use `''` for backwards compatibility with deprecated code.
crumbEvent: urlSearchParams.get(eventKey) ?? '',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a weird behavior. We should not confuse '' and null | undefined.

@oatkiller oatkiller requested a review from dplumlee August 13, 2020 18:00
@oatkiller oatkiller added release_note:skip Skip the PR/issue when compiling release notes and removed release_note:fix labels Aug 13, 2020
Copy link
Contributor

@kqualters-elastic kqualters-elastic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope https://github.com/elastic/kibana/pull/74979/files#diff-7ad9ae78b9b4a582e275042a28912d39R64 is the only way to make the bug appear and it doesn't happen when using the app, but good change still 👍

return {
selectedNode: urlSearchParams.getAll(`resolver-${this.resolverComponentInstanceID}-id`),
};
public get historyLocationSearch(): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with it, attempting to rename things that are built in and already have names usually just leads to more confusion imo

@@ -35,6 +34,8 @@ export const ResolverWithoutProviders = React.memo(
{ className, databaseDocumentID, resolverComponentInstanceID }: ResolverProps,
refToForward
) {
//
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird comment

describe('when the resolver component has its component instance ID changed', () => {
const newInstanceID = 'newID';
beforeEach(() => {
simulator.resolverComponentInstanceID = newInstanceID;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not using your setter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the setter you are looking for

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

@kbn/optimizer bundle module count

id value diff baseline
securitySolution 1909 -126 2035

async chunks size

id value diff baseline
securitySolution 7.2MB -143.4KB 7.3MB

page load bundle size

id value diff baseline
securitySolution 805.9KB -5.0B 805.9KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@oatkiller oatkiller merged commit 1729091 into elastic:master Aug 13, 2020
@oatkiller oatkiller deleted the test-query-string-stuff branch August 13, 2020 21:50
gmmorris added a commit to gmmorris/kibana that referenced this pull request Aug 14, 2020
* master: (23 commits)
  Adding API test for custom link transaction example (elastic#74238)
  [Uptime] Singular alert (elastic#74659)
  Revert "attempt excluding a codeowners directory" (elastic#75023)
  [Metrics UI] Remove TSVB dependency from Metrics Explorer APIs (elastic#74804)
  Remove degraded state from ES status service (elastic#75007)
  [Reporting/Functional] unskip pagination test (elastic#74973)
  [Resolver] Stale query string values are removed when resolver's component instance ID changes. (elastic#74979)
  Add public url to Workplace Search plugin (elastic#74991)
  [Reporting] Update more Server Types for TaskManager (elastic#74915)
  [I18n] verify select icu-message options are in english (elastic#74963)
  Make data.search.aggs available on the server. (elastic#74472)
  [Security Solution][Resolver] Graph Control Tests and Update Simulator Selectors (elastic#74680)
  attempt excluding a codeowners directory
  [ML] DF Analytics: allow failed job to be stopped by force via the UI (elastic#74710)
  Add kibana-core-ui-designers team (elastic#74970)
  [Metrics UI] Fix inventory footer misalignment (elastic#74707)
  Remove legacy optimizer (elastic#73154)
  Update design-specific GH code-owners (elastic#74877)
  skip test Reporting paginates content elastic#74922
  [Metrics UI] Add Jest tests for alert previews (elastic#74890)
  ...
oatkiller pushed a commit to oatkiller/kibana that referenced this pull request Aug 14, 2020
…onent instance ID changes. (elastic#74979)

The app can show more than 1 Resolver at a time. Each instance has a unique ID called the `resolverComponentInstanceID`. 
When the user interacts with Resolver it will add values to the query string. The query string values will contain the `resolverComponentInstanceID`. This allows each Resolver to keep its state separate. When resolver unmounts it will remove any query string values related to it.

If Resolver's `resolverComponentInstanceID` changes it should remove query string values related to the old instance ID. It does not. This PR fixes that. 

Note: I don't know if it was possible for this bug to actually happen. I can't make it happen, but depending on how Resolver is mounted by its consumers it *could*
oatkiller pushed a commit that referenced this pull request Aug 14, 2020
…onent instance ID changes. (#74979) (#75038)

The app can show more than 1 Resolver at a time. Each instance has a unique ID called the `resolverComponentInstanceID`. 
When the user interacts with Resolver it will add values to the query string. The query string values will contain the `resolverComponentInstanceID`. This allows each Resolver to keep its state separate. When resolver unmounts it will remove any query string values related to it.

If Resolver's `resolverComponentInstanceID` changes it should remove query string values related to the old instance ID. It does not. This PR fixes that. 

Note: I don't know if it was possible for this bug to actually happen. I can't make it happen, but depending on how Resolver is mounted by its consumers it *could*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Resolver Security Solution Resolver feature release_note:skip Skip the PR/issue when compiling release notes Team:Endpoint Data Visibility Team managing the endpoint resolver v7.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants